//泛型

//返回的类型和传入的类型一致
function echo<T>(arg: T):T{
  return arg;
}
const result = echo('hello');

console.log(result);
const number = echo(123);
console.log(number);

function swap<U,T>(tuple: [U,T]):[T,U]{
  return [tuple[1],tuple[0]]
}
const result2 = swap(['1223',3]);
console.log(result2[1]);


//这种写法就固定死了，必须要写成数组类型，数组中的值为T
function withLength<T>(arg:T[]): T[]{
  console.log(arg.length);
  return arg;
}
// 可以用extends 来扩展T

interface IwhitLenth {
  length:number;
}

function withLength2<T extends IwhitLenth>(arg:T):T {
  console.log(arg.length);
  return arg;
}

//这种写法可以传入数组，字符串，以及带length 属性的obj,
const array = withLength2([1,2]);
console.log(array);

const str = withLength2('str');
console.log(str);

const obj = withLength2({length:2,name:'moudong'});
console.log(obj)


// 在 class 中使用 泛型
class Calcultor {
  private num: number = 1;
  calc(arg: number):number {
    return this.num + arg
  }
}
const calcutor = new Calcultor();
//这样写就只能传入数字
let resNumber = calcutor.calc(1);

// class Quen {
//   private data = [];
//   push(arg) {
//     return this.data.push(arg);
//   }
//   pop() {
//     return this.data.shift();
//   }
// }

// const quen1 = new Quen();
// quen1.push(1)
// quen1.push('str')
// console.log(quen1.pop().toFixed())
// console.log(quen1.pop().toFixed())  //由于 这里取出的是 字符串，字符串不含有 toFixed方法，所有在运行的时候报错


class Quen<T> {
  private data:T[] = [];
  push(arg:T) {
    return this.data.push(arg)
  }
  pop():T {
    return this.data.shift();
  }
}

const quen1 = new Quen<number>();

quen1.push(1);

console.log(quen1.pop().toFixed())  //1
const quen2 = new Quen<string>()
quen2.push('str')
console.log(quen2.pop().length)   //3


//这个是用在接口上
interface IKeyPair<T,U> {
  key: T;
  value: U
}

const k1: IKeyPair<string,number> = {key:'str',value: 1}

const k2: IKeyPair<number,string> = {key:1,value:'string'}


// 还可以用在函数上
interface IPlus<T> {
  (a:T,b:T): T
}

function plus(a,b) {
   return a + b;
}

const plus1:IPlus<number> = plus;
const plus2:IPlus<string> = plus;

console.log(plus1(1,2));
console.log(plus2("a", "b"));





